package divestoclimb.checklist;

import java.io.File;
import java.net.URI;

import divestoclimb.checklist.R;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Because there are multiple file browsers out there and they all accept
 * different Intents and options, and because the user might not have any
 * installed, this class abstracts the process of calling an activity to
 * select a file or directory.
 * 
 * The class is extendable so the logic for what app to prefer can change
 * in the future depending on the capabilities of each and the parameters
 * requested.
 * TODO: support OI File Browser
 * @author Ben Roberts (divestoclimb@gmail.com)
 *
 */
public class FilePickerHelper {
	
	private static final int CODE_ANDEXPLORER = 801;
	private static final int CODE_INTERNAL = 802;
	
	private Activity mActivity;
	
	public FilePickerHelper(Activity a) {
		mActivity = a;
	}
	
	private String buildExtensionList(String[] extensions) {
		String extensionlist = "";
		boolean first = true;
		for(int c = 0; c < extensions.length; c++) {
			if(! first) {
				extensionlist += ",";
			} else {
				first = false;
			}
			extensionlist += "*."+extensions[c];
		}
		return extensionlist;
	}
	
	/**
	 * Launch an activity to select a directory
	 * @param start The initial path to open in the browser
	 * @param title The window title
	 * @param extensions An array of file extensions which will be used to
	 * determine what files to show in the listing.
	 */
	public void selectDirectory(File start, String title, String[] extensions) {
		// Prefer AndExplorer
		Intent i = new Intent(Intent.ACTION_PICK)
			.setDataAndType(Uri.fromFile(start), "vnd.android.cursor.dir/lysesoft.andexplorer.directory")
			.putExtra("explorer_title", title)
			// Optional 0=simple list, 1 = list with filename and size, 2 = list with filename, size and date.
			.putExtra("browser_list_layout", "0");
		if(extensions != null) {
			i.putExtra("browser_filter_extension_whitelist", buildExtensionList(extensions));
		}
		if(i.resolveActivity(mActivity.getPackageManager()) != null) {
			mActivity.startActivityForResult(i, CODE_ANDEXPLORER);
			return;
		}
		
		// Fall back on our internal activity
		i.setClass(mActivity, FilePicker.class)
			.replaceExtras((Bundle)null)
			.putExtra(FilePicker.PARAM_LOCATION, start.getPath())
			.putExtra(FilePicker.PARAM_TITLE, title)
			.putExtra(FilePicker.PARAM_TYPE, FilePicker.TYPE_DIRECTORY);
		mActivity.startActivityForResult(i, CODE_INTERNAL);
	}

	/**
	 * Launch an activity to select a file
	 * @param start The initial path to open in the browser
	 * @param title The window title
	 * @param mimeFilter A MIME type filter to add to the Intent, if the activity supports it
	 * @param extensions An array of file extensions which will be used to
	 * determine what files to show in the listing.
	 */
	public void selectFile(File start, String title, String mimeFilter, String[] extensions) {
		Intent i = new Intent();
		if(mimeFilter == "" && extensions != null) {
			// Prefer AndExplorer if an extension is specified
			i.setAction(Intent.ACTION_PICK)
				.setDataAndType(Uri.fromFile(start), "vnd.android.cursor.dir/lysesoft.andexplorer.file")
				.putExtra("browser_filter_extension_whitelist", buildExtensionList(extensions))
				.putExtra("explorer_title", title)
				// Optional 0=simple list, 1 = list with filename and size, 2 = list with filename, size and date.
				.putExtra("browser_list_layout", "2");
			if(i.resolveActivity(mActivity.getPackageManager()) != null) {
				mActivity.startActivityForResult(i, CODE_ANDEXPLORER);
				return;
			}
		}

		// If all else failed, use our internal activity
		i.setClass(mActivity, FilePicker.class)
			.putExtra(FilePicker.PARAM_LOCATION, start.getPath())
			.putExtra(FilePicker.PARAM_TITLE, title)
			.putExtra(FilePicker.PARAM_TYPE, FilePicker.TYPE_FILE);
		mActivity.startActivityForResult(i, CODE_INTERNAL);
	}
	
	public File getFileFromResult(int requestCode, int resultCode, Intent data) {
		if(resultCode == Activity.RESULT_OK) {
			switch(requestCode) {
			case CODE_ANDEXPLORER:
			case CODE_INTERNAL:
				Uri uri = data.getData();
				if (uri != null && uri.getScheme().compareTo("file") == 0) {
					// Selected file/directory path is below
					return new File(URI.create(uri.toString()));
				}
			}
		}
		return null;
	}
	
	/**
	 * This is our fallback file picker activity. It's just a EditText that
	 * lets the user key in a path name, and validates that it exists and is
	 * the correct type (file/directory).
	 * @author Ben Roberts (divestoclimb@gmail.com)
	 */
	public static class FilePicker extends Activity implements Button.OnClickListener {
		
		public static final String PARAM_TITLE = "title";
		public static final String PARAM_TYPE = "type";
		public static final String PARAM_LOCATION = "location";
		public static final int TYPE_FILE = 1;
		public static final int TYPE_DIRECTORY = 2;

		private int mType;
		private String mName;
		private EditText mEditText;

		@Override
		public void onCreate(Bundle icicle) {
			super.onCreate(icicle);
			setContentView(R.layout.file_picker);
			
			Bundle params = icicle != null? icicle: getIntent().getExtras();
			if(params != null) {
				mName = params.getString(PARAM_LOCATION);
				setTitle(params.getString(PARAM_TITLE));
				mType = params.getInt(PARAM_TYPE);
			}
			
			mEditText = (EditText)findViewById(R.id.content);
			
			TextView other_browsers = (TextView)findViewById(R.id.other_browsers);
			other_browsers.setMovementMethod(LinkMovementMethod.getInstance());
			
			// Set up our button listener
			Button ok = (Button) findViewById(R.id.button_ok);
			ok.setOnClickListener(this);
			Button cancel = (Button) findViewById(R.id.button_cancel);
			cancel.setOnClickListener(this);
		}
		
		@Override
		protected void onSaveInstanceState(Bundle outState) {
			super.onSaveInstanceState(outState);
			outState.putString(PARAM_LOCATION, mEditText.getText().toString());
		}
		
		@Override
		protected void onResume() {
			super.onResume();
			mEditText.setText(mName);
		}

		public void onClick(View v) {
			switch(v.getId()) {
			case R.id.button_ok:
				File path = new File(mEditText.getText().toString());
				if(mType == TYPE_FILE && path.isFile() || mType == TYPE_DIRECTORY && path.isDirectory()) {
					Intent result = new Intent().setData(Uri.fromFile(path));
					setResult(RESULT_OK, result);
					finish();
				} else {
					Toast.makeText(this, mType == TYPE_FILE? R.string.not_file: R.string.not_directory, Toast.LENGTH_SHORT).show();
				}
				break;
			case R.id.button_cancel:
				finish();
			}
		}
	}
}